/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/


#include "stdafx.h"
#include <pgl/core/pgl.h>
#include <pgl/core/PGLLinearGradientBrush.h>
#include <pgl/core/PGLRegion.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


PGL_IMPLEMENT_DYNCREATE(CPGLLinearGradientBrush, CPGLBrush);

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//! Save settings
void CPGLLinearGradientBrush::SerializeXML(CPGLArchive& ar)
{
	static TCHAR szTag[] = _T("CPGLLinearGradientBrush");

	CString str;
	markup::CMarkupArchive& xml = *((markup::CMarkupArchive*)ar.GetMarkup());
	if(ar.IsStoring())
	{
		xml.AddChildElem(szTag);
		xml.IntoElem();
			CPGLBrush::SerializeXML(ar);
			xml.AddChildElem(_T("StartColor"));
			xml.IntoElem();
				m_cStart.SerializeXML(ar);
			xml.OutOfElem();

			xml.AddChildElem(_T("EndColor"));
			xml.IntoElem();
				m_cEnd.SerializeXML(ar);
			xml.OutOfElem();

			xml.AddChildElemEx(_T("Angle"),m_dAngle);

		xml.OutOfElem();
	}
	else
	{
		if  (!xml.FindChildElem(szTag))
				return;

		xml.IntoElem();
			CPGLBrush::SerializeXML(ar);

			xml.ResetChildPos();
			if (xml.FindChildElem(_T("StartColor")))
			{
				xml.IntoElem();
					m_cStart.SerializeXML(ar);
				xml.OutOfElem();
			}

			xml.ResetChildPos();
			if (xml.FindChildElem(_T("EndColor")))
			{
				xml.IntoElem();
					m_cEnd.SerializeXML(ar);
				xml.OutOfElem();
			}

			xml.FindGetChildData(_T("Angle"),m_dAngle);

		xml.OutOfElem();
	}
}

#ifdef _DEBUG
void CPGLLinearGradientBrush::Dump( CDumpContext& dc ) const
{
    // call base class function first
    CPGLBrush::Dump( dc );

    // now do the stuff for our specific class
	dc << _T("CPGLLinearGradientBrush \n");
}
void CPGLLinearGradientBrush::AssertValid() const
{
    // call inherited AssertValid first
    CPGLBrush::AssertValid();

} 
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPGLLinearGradientBrush::CPGLLinearGradientBrush(const CPGLColor& cStart, const CPGLColor& cEnd, double dAngle, const CPGLRectD& rBBox)
: CPGLBrush(rBBox), m_cStart(cStart), m_cEnd(cEnd), m_dAngle(dAngle)
{
}

CPGLLinearGradientBrush::~CPGLLinearGradientBrush()
{

}

CPGLLinearGradientBrush& CPGLLinearGradientBrush::operator = (const CPGLLinearGradientBrush& brush)
{
	if (this != &brush)
	{
		this->CPGLBrush::operator=(brush);

		m_cStart = brush.m_cStart;
		m_cEnd = brush.m_cEnd;
		m_dAngle = brush.m_dAngle;
	}
	return *this;
}

void CPGLLinearGradientBrush::MakeCurrentFill(gfxinterface::CGfxInterface& gfx)
{
	using namespace gfxinterface;

	double r = sqrt( m_rBBox.GetHeight()*m_rBBox.GetHeight()+  m_rBBox.GetWidth()*m_rBBox.GetWidth() );
	double cx=(m_rBBox.left+m_rBBox.right)/2;
	double cy=(m_rBBox.top+m_rBBox.bottom)/2;
	double theta = m_dAngle/180*PGL_PI;
	SPointD point1, point2;

	point1=SPointD( __max( m_rBBox.left, __min( m_rBBox.right, cx-r*cos(theta) ) ),
			__max( m_rBBox.bottom, __min( m_rBBox.top, cy-r*sin(theta) ) ) );
	point2=SPointD( __max( m_rBBox.left, __min( m_rBBox.right, cx+r*cos(theta) ) ),
			__max( m_rBBox.bottom, __min( m_rBBox.top, cy+r*sin(theta) ) ) );
	
	gfx.SetLinearGradientFill(point1, point2, m_cStart.GetRGBA(), m_cEnd.GetRGBA()); 
}
